原型模式通過讓物件提供複製方法,讓使用者能夠輕鬆複製物件。
假設你是世界名畫「蒙娜麗莎的微笑」的收藏家。你經常收到美術館的來信,邀請展出這幅畫作。由於這幅畫極為珍貴,你不希望將它借出,但是你又無法拒絕那些誠摯的請求。於是,你想出了一個辦法,使用最先進的 3D 列印技術複製這幅畫,再將複製品借給美術館展覽。如此一來,不僅確保了畫作的安全,也實現了美術館的願望。雖然現實生活中沒有這麼便利的事,但在程式設計中,你可以透過原型模式來輕鬆複製物件。
假設我們有一個繪圖應用程式,可以繪製線條、圓形和矩形等幾何圖形。當使用者建立這些圖形後,他們可能會需要快速複製某些圖形。我們可以透過原型模式來實現圖形的複製功能。每一個圖形物件都可以有一個內建的複製方法,使用者只需選取圖形,即可輕鬆建立相同的圖形。
定義圖形原型,其中的抽象方法 clone
要求每個具體圖形實現自訂的複製功能。
abstract class Shape {
public x: number;
public y: number;
public color: string;
constructor(options: ShapeOptions) {
this.x = options.x;
this.y = options.y;
this.color = options.color || "black";
}
abstract clone(): Shape;
abstract toString(): string;
}
定義線條類別,使用者可以透過方法 clone
快速複製一個線條實體。
class Line extends Shape {
public length: number;
constructor(options: LineOptions) {
super(options);
this.length = options.length;
}
clone() {
return new Line(this);
}
toString() {
return `Line of length ${this.length}, starting at (${this.x}, ${this.y}), color: ${this.color}`;
}
}
接下來,我們來設計畫布類別。畫布物件將使用者建立的所有圖形記錄在一個陣列中。我們可以在畫布上添加各種圖形,再利用方法 describe
印出所有圖形資訊。
class Canvas {
private shapes: Shape[];
constructor() {
this.shapes = [];
}
addShape(shape: Shape) {
this.shapes.push(shape);
}
describe() {
console.log("Describing all shapes on the canvas:");
for (const shape of this.shapes) {
console.log(shape.toString());
}
}
}
測試時間。
class CanvasTestDrive {
static main() {
const canvas = new Canvas();
const line = new Line({ x: 10, y: 10, length: 20 });
const circle = new Circle({ x: 5, y: 5, radius: 10 });
const rectangle = new Rectangle({ x: 15, y: 15, width: 30, height: 10 });
const circleClone = circle.clone();
const rectangleClone = rectangle.clone();
canvas.addShape(line);
canvas.addShape(circle);
canvas.addShape(rectangle);
canvas.addShape(circleClone);
canvas.addShape(rectangleClone);
canvas.describe();
}
}
CanvasTestDrive.main();
輸出結果。
Describing all shapes on the canvas:
Line of length 20, starting at (10, 10), color: black
Circle with radius 10, centered at (5, 5), color: black
Rectangle of width 30 and height 10, positioned at (15, 15), color: black
Circle with radius 10, centered at (5, 5), color: black
Rectangle of width 30 and height 10, positioned at (15, 15), color: black
原型模式通過定義複製方法讓使用者快速複製一個物件。使用者只需透過複製方法複製物件,而不需依賴物件類別和建構邏輯,這讓物件複製變得非常容易。由於複製方法來自於物件本身,使用者可以連同物件的私有屬性一起複製。此外,原型模式使用建構式建立物件,因此複製出來的物件也保有所有類別方法。
當一個複雜的物件需要頻繁的被複製時,原型模式能夠有效簡化建構邏輯,提升程式的維護性。同時,透過共享資料,原型模式還能夠節省資源並提高效能。
https://github.com/chengen0612/design-patterns-typescript/blob/main/patterns/creational/prototype.ts